﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PickGold
{
	/// <summary>
	/// 表示时间间隔的类
	/// </summary>
	public class CPeriod : IPeriod
	{
		//
		public const double PRECISION = -1000;
		//
		private DateTime _From = DateTime.MinValue;
		private DateTime _To = DateTime.MinValue;
		//
		public CPeriod() { }
		public CPeriod(EPeriod period) : this(DateTime.Now, period) { }
		public CPeriod(DateTime from, DateTime to)
		{
			this._From = from;
			this._To = to;
		}
		public CPeriod(DateTime value, EPeriod period)
		{
			if (period == EPeriod.AllMonth)
				period = EPeriod.ThisYear;
			switch (period)
			{
				case EPeriod.OneYear:
					this._From = value.AddYears(-1);
					this._To = value;
					return;
				case EPeriod.OneQuarter:
					this._From = value.AddMonths(-3);
					this._To = value;
					return;
				case EPeriod.OneMonth:
					this._From = value.AddMonths(-1);
					this._To = value;
					return;
				case EPeriod.OneWeek://周
					this._From = value.AddDays(-7);
					this._To = value;
					return;
				case EPeriod.OneDay://天
					this._From = value.AddDays(-1);
					this._To = value;
					return;
				//
				case EPeriod.PreYear:
					this._From = new DateTime(value.Year - 1, 1, 1);
					this._To = new DateTime(value.Year, 1, 1).AddMilliseconds(PRECISION);//今年减一毫秒
					return;
				case EPeriod.PreQuarter:
					if (value.Month >= 0 && value.Month <= 2)
					{
						this._From = new DateTime(value.Year - 1, 9, 1);
						this._To = new DateTime(value.Year, 1, 1).AddMilliseconds(PRECISION);//今年减一毫秒
					}
					else if (value.Month >= 3 && value.Month <= 5)
					{
						this._From = new DateTime(value.Year, 0, 1);
						this._To = new DateTime(value.Year, 3, 1).AddMilliseconds(PRECISION);//减一毫秒
					}
					else if (value.Month >= 6 && value.Month <= 8)
					{
						this._From = new DateTime(value.Year, 3, 1);
						this._To = new DateTime(value.Year, 6, 1).AddMilliseconds(PRECISION);//减一毫秒
					}
					else //if (value.Month >= 9 && value.Month <= 11)
					{
						this._From = new DateTime(value.Year, 6, 1);
						this._To = new DateTime(value.Year, 9, 1).AddMilliseconds(PRECISION);//明年减一毫秒
					}
					return;
				case EPeriod.PreMonth:
					value = value.AddMonths(-1);
					this._From = new DateTime(value.Year, value.Month, 1);
					value = value.AddMonths(1);
					this._To = new DateTime(value.Year, value.Month, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.PreWeek://周
					this._From = value.AddDays((WeekDay(value) + 7) * -1);
					this._To = this._From.AddDays(6).AddMilliseconds(PRECISION);//加一周加一天减一毫秒
					return;
				case EPeriod.PreDay://天
					this._From = value.Date.AddDays(-1);
					this._To = value.Date.AddMilliseconds(PRECISION);//加一天减一毫秒
					return;
				//
				case EPeriod.ThisYear:
					this._From = new DateTime(value.Year, 1, 1);
					this._To = new DateTime(value.Year + 1, 1, 1).AddMilliseconds(PRECISION);//今年减一毫秒
					return;
				case EPeriod.ThisQuarter:
					if (value.Month >= 0 && value.Month <= 2)
					{
						this._From = new DateTime(value.Year, 1, 1);
						this._To = new DateTime(value.Year, 3, 1).AddMilliseconds(PRECISION);//今年减一毫秒
					}
					else if (value.Month >= 3 && value.Month <= 5)
					{
						this._From = new DateTime(value.Year, 3, 1);
						this._To = new DateTime(value.Year, 6, 1).AddMilliseconds(PRECISION);//减一毫秒
					}
					else if (value.Month >= 6 && value.Month <= 8)
					{
						this._From = new DateTime(value.Year, 6, 1);
						this._To = new DateTime(value.Year, 9, 1).AddMilliseconds(PRECISION);//减一毫秒
					}
					else //if (value.Month >= 9 && value.Month <= 11)
					{
						this._From = new DateTime(value.Year, 9, 1);
						this._To = new DateTime(value.Year + 1, 1, 1).AddMilliseconds(PRECISION);//明年减一毫秒
					}
					return;
				case EPeriod.ThisMonth:
					this._From = new DateTime(value.Year, value.Month, 1);
					value = value.AddMonths(1);
					this._To = new DateTime(value.Year, value.Month, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.ThisWeek://周
					this._From = value.AddDays(WeekDay(value) * -1);
					this._To = this._From.AddDays(6).AddMilliseconds(PRECISION);//加一周加一天减一毫秒
					return;
				case EPeriod.ThisDay://天
					this._From = value.Date;
					this._To = value.Date.AddDays(1).AddMilliseconds(PRECISION);//加一天减一毫秒
					return;
				//
				case EPeriod.NextYear:
					this._From = new DateTime(value.Year + 1, 1, 1);
					this._To = new DateTime(this._From.Year + 1, 1, 1).AddMilliseconds(PRECISION);//后年减一毫秒
					return;
				case EPeriod.NextQuarter:
					if (value.Month >= 0 && value.Month <= 2)
					{
						this._From = new DateTime(value.Year, 3, 1);
						this._To = new DateTime(value.Year, 6, 1).AddMilliseconds(PRECISION);//今年减一毫秒
					}
					else if (value.Month >= 3 && value.Month <= 5)
					{
						this._From = new DateTime(value.Year, 6, 1);
						this._To = new DateTime(value.Year, 9, 1).AddMilliseconds(PRECISION);//减一毫秒
					}
					else if (value.Month >= 6 && value.Month <= 8)
					{
						this._From = new DateTime(value.Year, 9, 1);
						this._To = new DateTime(value.Year + 1, 1, 1).AddMilliseconds(PRECISION);//减一毫秒
					}
					else //if (value.Month >= 9 && value.Month <= 11)
					{
						this._From = new DateTime(value.Year + 1, 1, 1);
						this._To = new DateTime(value.Year + 1, 3, 1).AddMilliseconds(PRECISION);//明年减一毫秒
					}
					return;
				case EPeriod.NextMonth:
					value = value.AddMonths(1);
					this._From = new DateTime(value.Year, value.Month, 1);
					value = value.AddMonths(1);
					this._To = new DateTime(value.Year, value.Month, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.NextWeek://周
					this._From = value.AddDays(7 - WeekDay(value));
					this._To = this._From.AddDays(6).AddMilliseconds(PRECISION);//加一周加一天减一毫秒
					return;
				case EPeriod.NextDay://天
					value = value.AddDays(1);
					this._From = value.Date;
					this._To = value.Date.AddDays(1).AddMilliseconds(PRECISION);//加一天减一毫秒
					return;
				//
				case EPeriod.January:
					this._From = new DateTime(value.Year, 1, 1);
					this._To = new DateTime(value.Year, 2, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.February:
					this._From = new DateTime(value.Year, 2, 1);
					this._To = new DateTime(value.Year, 3, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.March:
					this._From = new DateTime(value.Year, 3, 1);
					this._To = new DateTime(value.Year, 4, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.April:
					this._From = new DateTime(value.Year, 4, 1);
					this._To = new DateTime(value.Year, 5, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.May:
					this._From = new DateTime(value.Year, 5, 1);
					this._To = new DateTime(value.Year, 6, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.June:
					this._From = new DateTime(value.Year, 6, 1);
					this._To = new DateTime(value.Year, 7, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.July:
					this._From = new DateTime(value.Year, 7, 1);
					this._To = new DateTime(value.Year, 8, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.August:
					this._From = new DateTime(value.Year, 8, 1);
					this._To = new DateTime(value.Year, 9, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.September:
					this._From = new DateTime(value.Year, 9, 1);
					this._To = new DateTime(value.Year, 10, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.October:
					this._From = new DateTime(value.Year, 10, 1);
					this._To = new DateTime(value.Year, 11, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.November:
					this._From = new DateTime(value.Year, 11, 1);
					this._To = new DateTime(value.Year, 12, 1).AddMilliseconds(PRECISION);
					return;
				case EPeriod.December:
					this._From = new DateTime(value.Year, 12, 1);
					this._To = new DateTime(value.Year + 1, 1, 1).AddMilliseconds(PRECISION);
					return;
				//
				default:
					this._From = value;
					this._To = value;
					return;
			}
			//
		}
		//
		public DateTime From
		{
			set
			{
				this._From = value;
			}
			get
			{
				if (this._To > this._From)
					return this._From;
				return this._To;
			}
		}
		//
		public DateTime To
		{
			set
			{
				this._To = value;
			}
			get
			{
				if (this._From > this._To)
					return this._From;
				return this._To;
			}
		}
		//
		public DateTime EndDayOfTo
		{
			set
			{
				this._To = value.Date.AddDays(1).AddMilliseconds(PRECISION);
			}
			get
			{
				return this.To.Date.AddDays(1).AddMilliseconds(PRECISION);
			}
		}
		//
		public DateTime NextDayOfTo
		{
			set
			{
				this._To = value.Date.AddMilliseconds(PRECISION);
			}
			get
			{
				return this.To.Date.AddDays(1);
			}
		}

		/// <summary>
		/// 计算指定时间为一周的第几天，周日为第一天：索引为零
		/// </summary>
		/// <param name="value">时间</param>
		/// <returns>指定时间为一周的第几天</returns>
		public static int WeekDay(DateTime value)
		{
			switch (value.DayOfWeek)
			{
				case DayOfWeek.Sunday:
					return 0;
				case DayOfWeek.Monday:
					return 1;
				case DayOfWeek.Tuesday:
					return 2;
				case DayOfWeek.Wednesday:
					return 3;
				case DayOfWeek.Thursday:
					return 4;
				case DayOfWeek.Friday:
					return 5;
				case DayOfWeek.Saturday:
					return 6;
				//default:
				//	return 0;
			}

			return 0;
		}

		/// <summary>
		/// End Day Of To
		/// </summary>
		/// <param name="dateTime">date time</param>
		/// <returns>date time</returns>
		public static DateTime GetEndDayOfTo(DateTime dateTime)
		{
			return dateTime.Date.AddDays(1).AddMilliseconds(PRECISION);
		}
		//
		public static DateTime GetNextDayOfTo(DateTime dateTime)
		{
			return dateTime.Date.AddDays(1);
		}
		//
	}
}
